# -*- coding: utf-8 -*-
# created on 2016/6/20

import itertools
import os
import pandas
import re
from mathsolver.base import Rule


def _readin_rules(lines):
    raw_rules = []
    rule = {}
    iff, then = True, False
    name = ""
    for i, line in enumerate(lines):
        line = line.strip()
        if len(line) == 0:
            continue
        elif line[0] == "#":
            name = line.split(" ")[0]
            if not name or name.replace("#", "").isdigit():
                name = ""
                continue
            else:
                name = name.replace("#", "")
                continue

        line = line.replace(" ", "")
        if line == "IF:":
            if "steps" in rule:
                assert then, "%d:%s" % (i, line)
                raw_rules.append(rule)
            rule = {"name": name}
            iff, then = True, False

        if iff and "question=" in line:
            rule["question"] = line.split("question=", 1)[1].strip('"').split('"OR"')
        elif iff and "condition=" in line:
            condition = line.split("condition=", 1)[1].strip('"')
            if "OR" in line:
                rule["condition"] = condition.split('"OR"')
            elif "&&" in line:
                rule["condition"] = [condition.replace('"&&"', "&&")]
            else:
                rule["condition"] = [condition]

        if line == "THEN:":
            assert iff
            rule["steps"] = []
            iff, then = False, True
        elif then:
            step = {"output": ""}
            if "=" in line:
                output, line = line.split("=")
                step["output"] = output

            if "if(" == line[:3]:
                continue
            else:
                search = re.search("([A-Za-z0-9_]+)\\((.*)\\)", line)
                if search:
                    step["func"] = search.group(1)
                    step["input"] = [inp for inp in search.group(2).split(",") if inp]
                else:
                    raise ValueError("invalid rule format:", i, line)
            rule["steps"].append(step)

    if rule and then and (
            ("condition" in rule and "".join(rule["condition"])) or ("question" in rule and "".join(rule["question"]))):
        raw_rules.append(rule)

    return raw_rules


def readin_rules():
    filelist = os.listdir("mathsolver/rules/")
    raw_rules = []
    for filename in filelist:
        raw_rules += _readin_rules(open("mathsolver/rules/%s" % filename))
    # raw_rules += _readin_rules(open("mathsolver/rules/rule_tmp.txt"))
    return raw_rules


def init_rule(raw_rules, start_index=0):
    rules = []
    db = []
    for i, rule in enumerate(raw_rules, start_index):
        rule["id"] = i
        if "condition" not in rule:
            rule["condition"] = [""]

        if "question" not in rule:
            rule["question"] = [""]

        for q, c in itertools.product(rule["question"], rule["condition"]):
            db.append([i, q, c])
        rules.append(Rule(rule))
    return rules, pandas.DataFrame.from_records(db, columns=["id", "question", "condition"])


def generate_all(db):
    all_conditions = set()
    for condition in db["condition"]:
        if "&&" in condition:
            all_conditions.update(condition.split("&&"))
        else:
            all_conditions.add(condition)

    all_conditions.difference_update([""])
    all_questions = set(db["question"]).difference([""])
    return all_conditions, all_questions


def rulebase_start():
    raw_rules = readin_rules()
    rules, db = init_rule(raw_rules)
    all_conditions, all_questions = generate_all(db)
    db[db.condition == "eq&&ineqs"]["id"].tolist()
    return db, rules, all_conditions, all_questions


if __name__ == '__main__':
    pass
